﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using FFACETools;
using System.Diagnostics;
using System.Collections;
using System.Threading;

namespace SMN
{
    public partial class Form1 : Form
    {
        FFACE _FFACE { get; set; }

        private List<String> _Avatars = new List<String>();
        private Hashtable _Staves = new Hashtable();
        private Hashtable __Staves = new Hashtable();
        private DateTime _StartDate = DateTime.Now;
        private DateTime _EndDate = DateTime.Now;
        private String _Spell = String.Empty;
        private Hashtable _Equivalent = new Hashtable();

        public Form1()
        {
            InitializeComponent();
            Process[] Pol = Process.GetProcessesByName("pol");
            if (Pol.Length < 1)
            {
                if (MessageBox.Show("FFXI Is not running, application will close.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error) == DialogResult.OK)
                {
                    System.Environment.Exit(0);
                }
            }

            try
            {
                this.StartProcess(Pol[0].Id);
                this.AsName();
                this.SMNSkill();
                this.ModifyHpMp();
            }
            catch (Exception Ex)
            {
                MessageBox.Show("Error: " + Ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            this.FillStaves();
            this.LoopAvatarCheckBoxes();
            this.LoopSpiritCheckBoxes();
            this.LoopStavesCheckBoxes();
        }

        private void StartProcess(int ProcessId)
        {
            _FFACE = new FFACE(ProcessId);
        }

        private void ModifyHpMp()
        {
            this.lbMP.Text = _FFACE.Player.MPMax.ToString() + "/" + _FFACE.Player.MPCurrent.ToString() + " " + _FFACE.Player.MPPCurrent.ToString() + "%";
            this.lbHP.Text = _FFACE.Player.HPMax.ToString() + "/" + _FFACE.Player.HPCurrent.ToString() + " " + _FFACE.Player.HPPCurrent.ToString() + "%";
        }

        private void AsName()
        {
            this.lbName.Text = _FFACE.Player.Name;
        }

        private void SMNSkill()
        {
            this.lbSkill.Text = _FFACE.Player.GetMagicSkillDetails(MagicSkill.Summoning).Level.ToString();
            if (!_FFACE.Player.GetMagicSkillDetails(MagicSkill.Summoning).Capped)
            {
                this.lbStatus.Text = "Skill not capped.";
            }
            else
            {
                this.lbStatus.Text = "Skill is capped, Program has finished.";
                this.Done = true;
            }
        }

        private void LoopAvatarCheckBoxes()
        {
            foreach (Control Ctrl in this.groupBox2.Controls)
            {
                if (Ctrl is CheckBox)
                {
                    CheckBox cb = (CheckBox)Ctrl;
                    if (cb.CheckState == CheckState.Checked)
                    {
                        if (!_Avatars.Contains(cb.Text))
                        {
                            this._Avatars.Add(cb.Text);
                        }
                    }
                }
            }
        }

        private void LoopSpiritCheckBoxes()
        {
            String Spirit = " Spirit";
            foreach (Control Ctrl in this.groupBox3.Controls)
            {
                if (Ctrl is CheckBox)
                {
                    CheckBox cb = (CheckBox)Ctrl;
                    if (cb.CheckState == CheckState.Checked)
                    {
                        if (!_Avatars.Contains(cb.Text + Spirit))
                        {
                            this._Avatars.Add(cb.Text + Spirit);
                        }
                    }
                }
            }
        }

        private void LoopStavesCheckBoxes()
        {
            foreach (Control Ctrl in this.groupBox5.Controls)
            {
                if (Ctrl is CheckBox)
                {
                    CheckBox Cb = (CheckBox)Ctrl;
                    if (Cb.CheckState == CheckState.Checked)
                    {
                        if (Cb.Name.Length == 5)
                        {
                            String[] Name = { Cb.Name.Substring(0, 1), Cb.Name.Substring(1, 2) };
                            this.AddStaff(Name);
                        }
                        else if (Cb.Name.Length == 6)
                        {
                            String[] Name = { Cb.Name.Substring(0, 2), Cb.Name.Substring(2, 2) };
                            this.AddStaff(Name);
                        }
                    }
                }
            }
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            CheckBox cb = (CheckBox)sender;
            if (cb.CheckState == CheckState.Checked)
            {
                if (!this._Avatars.Contains(cb.Text))
                {
                    this._Avatars.Add(cb.Text);
                }
            }
            else if (cb.CheckState == CheckState.Unchecked)
            {
                if(this._Avatars.Contains(cb.Text))
                {
                    this._Avatars.Remove(cb.Text);
                }
            }
        }

        private void checkBox26_CheckedChanged(object sender, EventArgs e)
        {
            CheckBox cb = (CheckBox)sender;
            String Spirit = " Spirit";
            if (cb.CheckState == CheckState.Checked)
            {
                if (!this._Avatars.Contains(cb.Text + Spirit))
                {
                    this._Avatars.Add(cb.Text + Spirit);
                }
            }
            else if (cb.CheckState == CheckState.Unchecked)
            {
                if (this._Avatars.Contains(cb.Text + Spirit))
                {
                    this._Avatars.Remove(cb.Text + Spirit);
                }
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            SMN.Properties.Settings.Default.Save();
        }

        private void FillStaves()
        {
            Hashtable NQStaves = new Hashtable();
            NQStaves.Add("L", "Light Staff");
            NQStaves.Add("D", "Dark Staff");
            NQStaves.Add("W", "Water Staff");
            NQStaves.Add("E", "Earth Staff");
            NQStaves.Add("I", "Ice Staff");
            NQStaves.Add("Wi", "Wind Staff");
            NQStaves.Add("F", "Fire Staff");
            NQStaves.Add("T", "Thunder Staff");

            Hashtable HQStaves = new Hashtable();
            HQStaves.Add("L", "HLight Staff");
            HQStaves.Add("D", "HDark Staff");
            HQStaves.Add("W", "HWater Staff");
            HQStaves.Add("E", "HEarth Staff");
            HQStaves.Add("I", "HIce Staff");
            HQStaves.Add("Wi", "HWind Staff");
            HQStaves.Add("F", "HFire Staff");
            HQStaves.Add("T", "HThunder Staff");

            this._Staves.Add("NQ", NQStaves);
            this._Staves.Add("HQ", HQStaves);

            this._Equivalent.Add("Carbuncle", "L");
            this._Equivalent.Add("Fenrir", "D");
            this._Equivalent.Add("Titan", "E");
            this._Equivalent.Add("Leviathan", "W");
            this._Equivalent.Add("Shiva", "I");
            this._Equivalent.Add("Garuda", "Wi");
            this._Equivalent.Add("Ifrit", "F");
            this._Equivalent.Add("Ramuh", "T");
            this._Equivalent.Add("Diabolos", "D");
            this._Equivalent.Add("Light Spirit", "L");
            this._Equivalent.Add("Dark Spirit", "D");
            this._Equivalent.Add("Earth Spirit", "E");
            this._Equivalent.Add("Water Spirit", "W");
            this._Equivalent.Add("Ice Spirit", "I");
            this._Equivalent.Add("Wind Spirit", "Wi");
            this._Equivalent.Add("Fire Spirit", "F");
            this._Equivalent.Add("Thunder Spirit", "T");
        }

        private void cbLNQ_CheckedChanged(object sender, EventArgs e)
        {
            String SName = String.Empty;
            String SQName = string.Empty;

            CheckBox Cb = (CheckBox)sender;
            CheckBox SCb = null;

            SName = Cb.Name;
            if (Cb.Name.Contains("N"))
            {
                SQName = Cb.Name.Replace("N", "H");
                SCb = (CheckBox)this.groupBox5.Controls[SQName];
            }
            else if (Cb.Name.Contains("H"))
            {
                SQName = Cb.Name.Replace("H", "N");
                SCb = (CheckBox)this.groupBox5.Controls[SQName];
            }
            SCb.Checked = !Cb.Checked;

            SName = SName.Remove(0, 2);
            SQName = SQName.Remove(0, 2);

            if (Cb.Name.Length == 5)
            {
                String[] SSName = { SName.Substring(0, 1), SName.Substring(1, 2) };
                String[] SSQName = { SQName.Substring(0, 1), SQName.Substring(1, 2) };

                this.AddRemove(SSName, SSQName);
            }
            if (Cb.Name.Length == 6)
            {
                String[] SSName = { SName.Substring(0, 2), SName.Substring(2, 2) };
                String[] SSQName = { SQName.Substring(0, 2), SQName.Substring(2, 2) };

                this.AddRemove(SSName, SSQName);
            }
        }

        private String ExtractSSName(String[] Name)
        {
            return ((Hashtable)this._Staves[Name[1]])[Name[0]].ToString();
        }

        private void AddStaff(String[] Name)
        {
            if (!this.__Staves.Contains(Name[0]))
            {
                this.__Staves.Add(Name[0], this.ExtractSSName(Name));
            }
        }

        private void RemoveStaff(String[] Name)
        {
            if (this.__Staves.Contains(Name[0]))
            {
                this.__Staves.Remove(Name[0]);
            }
        }

        private void AddRemove(String[] Name, String[] SName)
        {
            this.AddStaff(Name);
            this.RemoveStaff(SName);
        }

        private void dateTimePicker1_ValueChanged(object sender, EventArgs e)
        {
            _StartDate = ((DateTimePicker)sender).Value;
        }

        private void dateTimePicker2_ValueChanged(object sender, EventArgs e)
        {
            _EndDate = ((DateTimePicker)sender).Value;
        }

        private void closeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (!this.timer1.Enabled)
            {
                this.timer1.Enabled = true;
                ((Button)sender).Text = "Stop";
            }
            else
            {
                this.timer1.Enabled = false;
                ((Button)sender).Text = "Start";
            }
        }

        private bool Casting = false;
        private bool Resting = false;
        private bool Done = false;

        private void timer1_Tick(object sender, EventArgs e)
        {
            this.timer1.Enabled = false;

            if (Done)
            {
                if (this.cbLogoff.Checked)
                {
                    _FFACE.Windower.SendString("/logoff");
                }
            }
            else if ((_EndDate < DateTime.Now) && !Done)
            {
                this.Start();
            }
            else if ((_EndDate == _StartDate) && !Done)
            {
                this.Start();
            }
            else
            {
                if (this.cbLogoff.Checked)
                {
                    _FFACE.Windower.SendString("/logoff");
                }
            }
        }

        private void Start()
        {
            if (_FFACE.Player.MPCurrent < 20 && Resting == false && Done == false)
            {
                this.StartResting();
            }
            if (_FFACE.Player.MPPCurrent == 100 && Casting == false && Done == false)
            {
                this.StartCasting();
            }
        }

        private void StartResting()
        {
            Resting = true;
            Casting = !Resting;
            if (_FFACE.Player.Status != Status.Healing)
            {
                this.PrintCmd("/heal");
                Thread.Sleep(1000);
            }

            while (_FFACE.Player.MPCurrent < _FFACE.Player.MPMax)
            {
                Thread.Sleep(1000);
                this.SMNSkill();
            }
            this.timer1.Enabled = true;
        }

        private void StartCasting()
        {
            Casting = true;
            Resting = !Casting;

            if (_FFACE.Player.Status == Status.Healing)
            {
                this.PrintCmd("/heal");
                Thread.Sleep(1000);
            }

            while (_FFACE.Player.MPCurrent > 20)
            {
                foreach (String Spell in _Avatars)
                {
                    if (_FFACE.Player.MPCurrent < 20) { break; }

                    this.PrintCmd("/ma \"" + Spell + "<me>", Spell);

                    while (_FFACE.Player.CastPercentEx < 100) { Thread.Sleep(500); }

                    this.PrintCmd("/pet \"Release\" <me>");
                }
            }
            this.timer1.Enabled = true;
        }

        private void PrintCmd(String Cmd)
        {
            _FFACE.Windower.SendString(Cmd);
            this.lbCmd.Text = Cmd;
        }

        private void PrintCmd(String Cmd, String Spell)
        {
            this.PrintCmd(Cmd);
            if (this._Staves.ContainsKey(this._Equivalent[Spell]))
            {
                _FFACE.Windower.SendString("/equip main \"" + this.__Staves[this._Equivalent[Spell]] + "\"");
            }
        }

        private void timer2_Tick(object sender, EventArgs e)
        {
            try
            {
                this.ModifyHpMp();
                this.SMNSkill();
            }
            catch (Exception)
            {
                this.timer2.Enabled = false;
            }
        }
    }
}
